﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;

using Windows.UI.Xaml.Controls;

using SeriesManager.Control;
using SeriesManager.Model;
using SeriesManager.Enum;
using SeriesManager.Core;

using WinRTFramework.Common;

namespace SeriesManager.ViewModel
{
    public class SubscriptionViewModel : ViewModelBase
    {
        #region Properties

        private bool isEmpty = true;

        public ListCollectionView View 
        { 
            get; 
            private set; 
        }

        public ObservableCollection<SeriesModel> SelectedItems 
        { 
            get; 
            private set; 
        }

        public bool IsEmpty
        {
            get 
            {
                return this.isEmpty;
            }
            private set
            {
                base.SetProperty<bool>(ref this.isEmpty, value);
            }
        }

        #endregion

        #region DelegateProperties

        public DelegateCommand<ItemClickEventArgs> SelectionAllCommand
        {
            get;
            private set;
        }

        public DelegateCommand<ItemClickEventArgs> SelectionClearCommand
        {
            get;
            private set;
        }

        public DelegateCommand<ItemClickEventArgs> UnSubscribeCommand
        {
            get;
            private set;
        }

        public DelegateCommand<ItemClickEventArgs> ItemClickedCommand
        {
            get;
            private set;
        }

        public DelegateCommand<ItemClickEventArgs> WatchStateCommand
        {
            get;
            private set;
        }

        public DelegateCommand<ItemClickEventArgs> UnwatchStateCommand
        {
            get;
            private set;
        }

        #endregion

        public SubscriptionViewModel()
        {
            this.SelectedItems = new ObservableCollection<SeriesModel>();
            this.SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
            this.View = new ListCollectionView(AppX.Instance.Series);
            this.View.Filter = new Predicate<object>((S) => (S as SeriesModel).Subscription);
            this.View.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
            this.isEmpty = !this.View.Any();

            this.UnSubscribeCommand = new DelegateCommand<ItemClickEventArgs>(OnUnsubscribeExecuted, OnUnsubscribeCanExecute);
            this.ItemClickedCommand = new DelegateCommand<ItemClickEventArgs>(OnItemClickExecuted);
            this.SelectionClearCommand = new DelegateCommand<ItemClickEventArgs>(OnSelectionClearExecuted, OnSelectionClearCanExecute);
            this.SelectionAllCommand = new DelegateCommand<ItemClickEventArgs>(OnSelectionAllExecuted, OnSelectionAllCanExecute);
            this.WatchStateCommand = new DelegateCommand<ItemClickEventArgs>(OnWatchStateExecuted, OnWatchStateCanExecute);
            this.UnwatchStateCommand = new DelegateCommand<ItemClickEventArgs>(OnUnwatchStateExecuted, OnUnwatchStateCanExecute);
        }

        #region DelegateProperties

        private void OnWatchStateExecuted(ItemClickEventArgs e)
        {
            for (int i = 0; i < this.SelectedItems.Count; i++)
            {
                if (this.SelectedItems[i].State == WatchState.Unwatched)
                {
                    this.SelectedItems[i].State = WatchState.Watched;
                    TileManager.UpdateTile(this.SelectedItems[i].ID, this.SelectedItems[i].Unwatched.Count);
                    this.SelectedItems.RemoveAt(i);
                    i--;
                }
            }

            this.WatchStateCommand.NotifyCanExecuteChanged();
        }

        private bool OnWatchStateCanExecute(ItemClickEventArgs e)
        {
            return this.SelectedItems != null && this.SelectedItems.Any(E => E.State == WatchState.Unwatched);
        }

        private void OnUnwatchStateExecuted(ItemClickEventArgs e)
        {
            for (int i = 0; i < this.SelectedItems.Count; i++)
            {
                if (this.SelectedItems[i].State == WatchState.Watched || (this.SelectedItems[i].State == WatchState.UnAired && this.SelectedItems[i].Watched.Any()))
                {
                    this.SelectedItems[i].State = WatchState.Unwatched;
                    TileManager.UpdateTile(this.SelectedItems[i].ID, this.SelectedItems[i].Unwatched.Count);
                    this.SelectedItems.RemoveAt(i);
                    i--;
                }
            }

            this.UnwatchStateCommand.NotifyCanExecuteChanged();
        }

        private bool OnUnwatchStateCanExecute(ItemClickEventArgs e)
        {
            return this.SelectedItems != null && this.SelectedItems.Any(E => E.State == WatchState.Watched || (E.Watched.Any() && E.State == WatchState.UnAired));
        }

        private void OnSelectionClearExecuted(ItemClickEventArgs e)
        {
            this.SelectedItems.Clear();
        }

        private bool OnSelectionClearCanExecute(ItemClickEventArgs e)
        {
            return this.SelectedItems.Any();
        }

        private void OnSelectionAllExecuted(ItemClickEventArgs e)
        {
            foreach (SeriesModel series in this.View)
            {
                if (!this.SelectedItems.Any(S => S.ID == series.ID))
                {
                    this.SelectedItems.Add(series);
                }
            }
        }

        private bool OnSelectionAllCanExecute(ItemClickEventArgs e)
        {
            return this.SelectedItems != null && this.View.Any();
        }

        private void OnUnsubscribeExecuted(ItemClickEventArgs e)
        {
            var subscriptions = this.SelectedItems.ToList();

            foreach (var series in subscriptions)
            {
                series.Subscription = false;
            }

            this.View.Refresh();
        }

        private bool OnUnsubscribeCanExecute(ItemClickEventArgs e)
        {
            return this.SelectedItems != null && this.SelectedItems.Any();
        }

        private void OnItemClickExecuted(ItemClickEventArgs e)
        {
            var clickedItem = e.ClickedItem as SeriesModel;
            AppX.Instance.Current = clickedItem;
            base.NavigationService.Navigate<SeriesViewModel>(clickedItem.ID);
        }

        #endregion

        private void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.UnSubscribeCommand.NotifyCanExecuteChanged();
            this.SelectionClearCommand.NotifyCanExecuteChanged();
            this.WatchStateCommand.NotifyCanExecuteChanged();
            this.UnwatchStateCommand.NotifyCanExecuteChanged();
            base.NavigationBarIsOpen = this.SelectedItems.Any();
        }

        public override void OnNavigatedTo(object navigationParameter)
        {
            base.OnNavigatedTo(navigationParameter);

            this.View.Refresh();
            this.SelectionAllCommand.NotifyCanExecuteChanged();
        }
    }
}
